package top.tenebrous.termbor.rpc.provider.common;


import cn.hutool.core.collection.CollUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.tenebrous.termbor.rpc.common.annotation.RpcService;
import top.tenebrous.termbor.rpc.common.constants.RpcConstants;
import top.tenebrous.termbor.rpc.common.helper.RpcServiceHelper;
import top.tenebrous.termbor.rpc.common.scan.ClassScanner;
import top.tenebrous.termbor.rpc.protocol.meta.ServiceMeta;
import top.tenebrous.termbor.rpc.registry.RegistryService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @program: termbor-rpc
 * @description:
 * @author: yazhang6
 * @create: 2024-05-20 17:21
 **/
public class RpcServiceScanner extends ClassScanner {

    private static final Logger LOGGER = LoggerFactory.getLogger(RpcServiceScanner.class);

    public static Map<String, Object> doScannerWithRpcServiceAnnotationFilterAndRegistryService(
        String host, int port, String scanPackage, RegistryService registryService
    ) {
        Map<String, Object> handlerMap = new HashMap<>();
        List<String> classNameList = getClassNameList(scanPackage);
        if (CollUtil.isEmpty(classNameList)) {
            return handlerMap;
        }
        classNameList.stream().forEach((className) -> {
            try {
                Class<?> aClass = Class.forName(className);
                RpcService rpcService = aClass.getAnnotation(RpcService.class);
                if (Objects.nonNull(rpcService)) {
                    // 优先使用interfaceClass, interfaceClassName的name为空，再使用interfaceClassName
                    // 后续逻辑向注册中心注册服务元数据，同时向handlerMap中记录标注了RpcService注解的类实例
                    LOGGER.info("当前标注了RpcService注解的类实例名称:{}", aClass.getName());
                    ServiceMeta serviceMeta =
                        new ServiceMeta(getServiceName(rpcService), rpcService.version(), host, port,
                            rpcService.group(), getWeight(rpcService.weight()));
                    // 将元数据注册到注册中心
                    registryService.register(serviceMeta);

                    String key = RpcServiceHelper.buildServiceKey(serviceMeta.getServiceName(), serviceMeta.getServiceVersion()
                        , serviceMeta.getServiceGroup());
                    handlerMap.put(key, aClass.newInstance());
                }
            }catch (Exception e) {
                LOGGER.error("扫描RpcService注解类异常", e);
            }
        });
        return handlerMap;
    }

    private static String getServiceName(RpcService rpcService) {
        if (Objects.nonNull(rpcService.interfaceClass())) {
            return rpcService.interfaceClass().getName();
        }
        if (Objects.nonNull(rpcService.interfaceClassName())) {
            return rpcService.interfaceClassName();
        }
        return "";
    }

    private static int getWeight(int weight) {
        if (weight < RpcConstants.SERVICE_WEIGHT_MIN) {
            weight = RpcConstants.SERVICE_WEIGHT_MIN;
        }
        if (weight > RpcConstants.SERVICE_WEIGHT_MAX) {
            weight = RpcConstants.SERVICE_WEIGHT_MAX;
        }
        return weight;
    }
}
